#ifndef DETECTRESULT_HPP
#define DETECTRESULT_HPP
#include <opencv2/opencv.hpp>
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <vector>

#include <algorithm>

#define OUTSPEED

class DetectResult
{
public:

#ifdef OUTSPEED
    cv::Vec2d speed;
    cv::Vec2d xzlocation;
#else
    cv::Vec3d location;
    cv::Vec4d area;
#endif


    int objID;
    DetectResult()
        : objID(-1)
    #ifdef OUTSPEED
        , speed(0,0)
        , xzlocation(0,0)
    #else
        , location(0,0,0)
        , area(0,0,0,0)
    #endif
    {

    }

    DetectResult(const DetectResult& src)
        : objID(src.objID)
    #ifdef OUTSPEED
        , speed(src.speed)
        , xzlocation(src.xzlocation)
    #else
        , location(src.location)
        , area(src.area)
    #endif

    {

    }

    void operator=(const DetectResult& src)
    {
        objID=src.objID;

#ifdef OUTSPEED
        speed=src.speed;
        xzlocation=src.xzlocation;
#else
        location=src.location;
        area=src.area;
#endif
    }

    static bool LoadStream(const char *path, std::stringstream &ss)
    {
        std::ifstream ifs(path);
        if (!ifs.is_open())
            return false;
        ss << ifs.rdbuf();
        ifs.close();
        return true;
    }

    static std::string FileName(size_t index)
    {
        std::ostringstream oss;
        oss<<"../result/result_3d_"<<index<<".txt";
        return oss.str();
    }

#ifndef OUTSPEED
    bool Load(size_t index)
    {
        std::stringstream ss;
        std::string fp=FileName(index);
        //        std::cout<<"try load "<<fp<<"\n"<<std::flush;
        bool res=LoadStream(fp.c_str(), ss);
        if(res)
        {

            std::string str=ss.str();

            std::cout<<"load "<<fp<<"\n"<<str<<"\n";
            if(str.compare("none")==0)
            {
                objID=-1;
            }
            else
            {
                ss>>objID>>location[0]>>location[1]>>location[2];


            }
            //            remove(fp.c_str());
        }
        return res;
    }

    cv::Vec2d XY() const
    {
        return cv::Vec2d(location[0], location[2]);
    }
#else
    cv::Vec2d XY() const
    {
        return xzlocation;
    }

#endif

    void rm(size_t index)
    {
        remove(FileName(index).c_str());
    }
};


class DetectResultS
{
public:
    std::vector<DetectResult> human;
    DetectResultS()
    {

    }

    DetectResultS(const DetectResultS& src)
        : human(src.human.begin(), src.human.end())
    {

    }

    void operator=(const DetectResultS& src)
    {
        human.assign(src.human.begin(), src.human.end());
    }


    void Decode(std::string str)
    {
//        std::cout<<"decode\n"<<std::flush;

        human.clear();
        if(str.compare("none")==0)
        {
            return;
        }
//        std::cout<<"detect human\n"<<std::flush;
        std::istringstream iss(str);
        DetectResult dr;
#ifdef OUTSPEED
        while(iss>>dr.objID>>dr.xzlocation[0]>>dr.xzlocation[1]>>dr.speed[0]>>dr.speed[1])
#else
        while(iss>>dr.objID>>dr.location[0]>>dr.location[1]>>dr.location[2]>>dr.area[0]>>dr.area[1]>>dr.area[2]>>dr.area[3])
#endif
        {
            human.push_back(dr);
        }
    }

    void Decode1(std::string str)
    {
        str.erase(std::remove_if(str.begin(),
                                 str.end(),
                                 [](unsigned char x){return x==','|| x=='['|| x==']' || x=='\'';}),
                  str.end());

        Decode(str);
    }


    void Draw(cv::Mat &canvas, int step=80)
    {
        for(size_t i=0;i<human.size();i++)
        {
            char buf[128];
            sprintf(buf, "%d %.1f %g %.3f %.3f", human[i].objID,
                    atan2(human[i].speed[0], human[i].speed[1])*180/CV_PI,
                    cv::norm(human[i].speed),
                    human[i].xzlocation[0], human[i].xzlocation[1]);

            cv::putText(canvas, buf, cv::Point(0, step*(i+1)), cv::FONT_HERSHEY_COMPLEX, 2, cv::Scalar(0, 255, 0), 2, 8, 0);
        }
    }


    cv::Mat DPMat()
    {
        cv::Mat canvas(720,1280,CV_8UC3,cv::Scalar(0));

        Draw(canvas, 80);

        return canvas;

    }


};


#endif // DETECTRESULT_HPP

